#include "yocto/utest/run.hpp"
#include "core/cell-dyn.hpp"
#include "core/cell-dyn-mt.hpp"
#include "core/fcc.hpp"

#include "yocto/wtime.hpp"

using namespace FastMD;

YOCTO_UNIT_TEST_IMPL(cells)
{  
	
	const size_t m  = 10;
	const U3D    cr(m,m,m);
	const size_t np = cr.items() << 2;
	Frame        frame(3,np);
	frame.set_box( V3D(12,12,12) );
	CellDynamics   dyn(   frame, 4.0 );
	CellDynamicsMT dynMT( frame, 4.0 );
	
	FCC::Build( frame[ Frame::POSITIONS ], cr, frame.box, frame.ibox, 0.2 );
	
	std::cerr << "frame.particles=" << frame.particles << std::endl;
	
	const Cells &cells = dyn.GetCells();
	std::cerr << "cells.size=" << cells.size << std::endl;
	
	size_t count = 0;
	for( size_t i=0; i < cells.size.x; ++i )
	{
		for( size_t j=0; j < cells.size.y; ++j )
		{
			for( size_t k=0; k < cells.size.z; ++k )
			{
				const Cell &c = cells[ k * cells.zstp + j * cells.ystp + i ];
				std::cerr << "cell" << c.id << ":";
				const CellNode *node = c.inside;
				while( node )
				{
					++count;
					std::cerr << " " << node->index;
					node = node->next;
				}
				std::cerr << std::endl;
				std::cerr << "|_#links=" << c.links <<":";
				for( size_t l=0; l < c.links; ++l )
				{
					std::cerr << " " << c.link[l]->id << "@" << c.id.distance_to(c.link[l]->id);
				}
				std::cerr << std::endl;
			}
		}
	}
	std::cerr << "count= " << count << " / " << np << std::endl;
	
	std::cerr << "Testing Dispatch" << std::endl;
	//-- benchmarking dispatch
	wtime        chrono;
	double       ell   = 0;
	const size_t niter = 1000;
	
	for( size_t iter=0; iter < niter; ++iter )
	{
		FCC::Build( frame[ Frame::POSITIONS ], cr, frame.box, frame.ibox, 0.2 );
		chrono.start();
		dyn.dispatch_only( frame[0] );
		ell += chrono.query();
	}
	ell /= niter;
	std::cerr << "ellST=" << ell*1000 << " ms" << std::endl;
	 
	ell = 0;
	for( size_t iter=0; iter < niter; ++iter )
	{
		FCC::Build( frame[ Frame::POSITIONS ], cr, frame.box, frame.ibox, 0.2 );
		chrono.start();
		dynMT.dispatch_only( frame[0] );
		ell += chrono.query();
	}
	ell /= niter;
	std::cerr << "ellMT=" << ell*1000 << " ms" << std::endl;
	
	
	
}
YOCTO_UNIT_TEST_DONE()
